数据不平衡处理

数据不均衡问题指样本数据中不同类别的容量差异过大,这类数据集在特定的领域会更容易遇见,例如: 信用欺诈、垃圾邮件检测、客户流失以及广告点击等。在搭建这类数据集的分类模型,容易出现过拟合情况,因此需要对数据集进行一定的处理。

过采样处理

过采样,即上采样(Over Sampling,或者 Up-sample Minority),是通过对少数类别的样本进行随机重复抽样的方式,达到增强该类别数据的目的。实施的方法:

  • 最简单快速的方式是又放回的重复抽样,Sklearn 提供的 resample 方法可以实现方式
    Bootstrap >unfold
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    from sklearn.utils import resample
    import numpy as np
    import pandas as pd

    # 生成模拟数据
    label = np.random.choice([0,1], p=[.2, .8], size=(1000, 1))
    features = np.stack(
    [np.random.normal(i, np.random.random() * 10, size=1000) for i in range(5)],
    axis=1
    )

    data = pd.DataFrame(np.hstack((features, label)),
    columns=[f"col{i}" for i in range(5)] + ["label"])

    # 拆分出少数数据
    minority = data[data["label"]==0]
    majority = data[data["label"]==1]

    # 有放回重复抽样
    sample = resample(
    minority,
    replace=True, # 有放回
    n_samples=majority.shape[0],
    random_state=42
    )

    # 合并数据
    new = pd.concat([majority, sample], ignore_index=True)

采用该方法得到的样本,大类别样本容量和小类别样本容量相同。此外可以通过 imblearn 也可以实现简单随机抽样:

Bootstrap >unfold
1
2
3
4
5
6
7
8
9
from imblearn.over_sampling import RandomOverSampler

# 实例化对象
ros = RandomOversampler(
random_state=42,
sampling_strategy="not majority", # 仅对小类别样本抽样
)

nfeatures, nlabel = ros.fit_resample(data.drop("label"), data["label"])
  • 小类别样本生成方法,包括 SMOTE 方法,它是通过添加噪声、干扰数据进行生成小类别数据的方法;ADASYN 方法,对不同类别学习过程的难度水平(数据合成的量越大,那么其学习难度越大)调整权重分布
    Generate >unfold
    1
    2
    3
    4
    5
    6
    from imblearn.over_sampling import SMOTE, ADASYN
    # SMOTE 方法生成数据-默认使用的策略是 not majority
    nfeatures, nlabel = SMOTE().fit_resample(data.drop("label"), data["label"])

    # 使用 ADASYN 方法生成数据-默认使用策略是 not majority
    nfeatures, nlabel = ADASYN().fit_resample(X, y)

欠采样处理

欠采样,即下采样(Under Sampling,Down Sample Majority),方法上是通过减少类别中的多数类别样本数量来实现样本均衡,这种方法主要是降低大类别信息。最简单的方式是对大类别进行不放回的抽样:

Under Sampling >unfold
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
rom sklearn.utils import resample
import numpy as np
import pandas as pd

# 生成模拟数据
label = np.random.choice([0,1], p=[.2, .8], size=(1000, 1))
features = np.stack(
[np.random.normal(i, np.random.random() * 10, size=1000) for i in range(5)],
axis=1
)

data = pd.DataFrame(np.hstack((features, label)),
columns=[f"col{i}" for i in range(5)] + ["label"])

# 拆分出少数数据
minority = data[data["label"]==0]
majority = data[data["label"]==1]

# 有放回重复抽样
sample = resample(
majority,
replace=False, # 不放回
n_samples=minority.shape[0],
random_state=42
)

# 合并数据
new = pd.concat([minority, sample], ignore_index=True)

除了这种简单抽样的方式外,imblearn 提供了其他欠采样的方法,例如压缩最邻近数据。

样本组合

组合样本的方式是将数据重新分配,再进行训练的过程。整体的思路类似于模型集成的方式:从大样本中随机抽取数据和小样本数据进行训练,这样不同的数据集合生成不同模型;在预测阶段,通过投票的方法进行预测结果。

选择合适的模型

具错误类别惩罚模型

对于某些模型是成本敏感性的,例如支持向量机(SVM)的可以通过增加分类错误的类别,来提升模型鲁棒性。

SVM >unfold
1
2
3
4
5
6
7
8
9
from sklearn.svm import SVC

model = SVC(
kernal="linear",
class_weight="balanced", # 该参数用于调整模型类别权重
)

# 拟合模型
model.fit(feature, label)

基于决策树的模型

决策树模型在不平衡的数据上也会有相对较好的表现,这是因为该算法天然的具有从不同类别的信号中生成层次性结构的特点。特别是在决策树集成模型中(例如随机森林、梯度提升树等)能够通过单一算法模型,得到良好的表现

参考

  1. Over-sampling, Imblearn
  2. SMOTE for Imbalanced Classification with Python
  3. Haibo He, Yang Bai, ADASYN: Adaptive Synthetic Sampling Approach for Imbalanced Learning
  4. 宋天龙, Python 数据分析与数据化运营
作者

ZenRay

发布于

2021-03-02

更新于

2021-04-19

许可协议

CC BY-NC-SA 4.0